---
layout: docs
page_title: Setup guide - Azure Key Vault
description: Configure the key management secrets engine, and distribute the Vault-managed keys to the target Azure Key Vault instance.
---

> [!IMPORTANT]  
> **Documentation Update:** Product documentation, which were located in this repository under `/website`, are now located in [`hashicorp/web-unified-docs`](https://github.com/hashicorp/web-unified-docs), colocated with all other product documentation. Contributions to this content should be done in the `web-unified-docs` repo, and not this one. Changes made to `/website` content in this repo will not be reflected on the developer.hashicorp.com website.

# Setup guide - Azure Key Vault

To manage the lifecycle of the Azure Key Vault keys, you need to setup the
key management secrets engine using `azurekeyvault` provider.

## Setup

1. Enable the key management secrets engine.

    ```shell-session
    $ vault secrets enable keymgmt
    Success! Enabled the keymgmt secrets engine at: keymgmt/
    ```

1. Configure a KMS provider resource named, `example-kms`.

    ```shell-session
    $ vault write keymgmt/kms/example-kms \
        provider="azurekeyvault" \
        key_collection="keyvault-name" \
        credentials=client_id="a0454cd1-e28e-405e-bc50-7477fa8a00b7" \
        credentials=client_secret="eR%HizuCVEpAKgeaUEx" \
        credentials=tenant_id="cd4bf224-d114-4f96-9bbc-b8f45751c43f"
    ```

    The command specified the following:

    - The full path to this KMS provider instance in Vault
      (`keymgmt/kms/example-kms`).
    - A key collection, which corresponds to the name of the key vault instance
      in Azure.
    - The KMS provider is set to `azurekeyvault`.
    - Azure client ID credential, that can also be specified with
      `AZURE_CLIENT_ID` environment variable.
    - Azure client secret credential, that can also be specified with
      `AZURE_CLIENT_SECRET `environment variable.
    - Azure tenant ID credential, that can also be specified with
      `AZURE_TENANT_ID` environment variable.

<Tip title="API documentation">

Refer to the Azure Key Vault [API
documentation](/vault/api-docs/secret/key-management/azurekeyvault) for a
detailed description of individual configuration parameters.

</Tip>

## Usage 

1. Write a pair of RSA-2048 keys to the secrets engine. The following command
   will write a new key of type **rsa-2048** to the path `keymgmt/key/rsa-1`. 

    ```shell-session
    $ vault write keymgmt/key/rsa-1 type="rsa-2048"
    Success! Data written to: keymgmt/key/rsa-1
    ```

    The key management secrets engine currently supports generation of the key
    types specified in [Key
    Types](/vault/docs/secrets/key-management#key-types).

    Based on the
    [Compatibility](/vault/docs/secrets/key-management#compatibility) section of
    the documentation, Azure Key Vault currently supports use of RSA-2048,
    RSA-3072, and RSA-4096 key types.

1. Read the **rsa-1** key you created. Use JSON as the output and pipe that into
   `jq`.

    ```shell-session
    $ vault read -format=json keymgmt/key/rsa-1 | jq
    ```

1. To use the keys you wrote, you must distribute them to the key vault.
   Distribute the **rsa-1** key to the key vault at the path
   `keymgmt/kms/example-kms/key/rsa-1`.

    ```shell-session
    $ vault write keymgmt/kms/example-kms/key/rsa-1 \
        purpose="encrypt,decrypt" \
        protection="hsm"
    ```

    Here you are instructing Vault to distribute the key and specify that its
    purpose is only to encrypt and decrypt. The protection type is dependent on
    the cloud provider and the value is either `hsm` or `software`. In the case
    of Azure, you specify `hsm` for the protection type. The key will be
    securely delivered to the key vault instance according to the [Azure Bring
    Your Own
    Key](https://docs.microsoft.com/en-us/azure/key-vault/keys/byok-specification)
    (BYOK) specification.

1. You can list the keys that have been distributed to the Azure Key Vault instance.

    ```shell-session
    $ vault list keymgmt/kms/keyvault/key/
    Keys
    ----
    rsa-1
    ```

1. Rotate the rsa-1 key.

    ```shell-session
    $ vault write -f keymgmt/key/rsa-1/rotate
    Success! Data written to: keymgmt/key/rsa-1/rotate
    ```

1. Confirm successful key rotation by reading the key, and getting the value of
   `.data.latest_version`.

    ```shell-session
    $  vault read -format=json keymgmt/key/rsa-1 | jq '.data.latest_version'
    2
    ```

## Azure private link

The secrets engine can be configured to communicate with Azure Key Vault
instances using [Azure Private
Endpoints](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-overview).
Follow the guide at [Integrate Key Vault with Azure Private
Link](https://docs.microsoft.com/en-us/azure/key-vault/general/private-link-service?tabs=portal)
to set up a Private Endpoint for your target Key Vault instance in Azure. The
Private Endpoint must be network reachable by Vault. This means Vault needs to
be running in the same virtual network or a peered virtual network to properly
resolve the Key Vault domain name to the Private Endpoint IP address.

The Private Endpoint configuration relies on a correct [Azure Private
DNS](https://docs.microsoft.com/en-us/azure/dns/private-dns-overview)
integration. From the host that Vault is running on, follow the steps in
[Validate that the private link connection
works](https://docs.microsoft.com/en-us/azure/key-vault/general/private-link-service?tabs=portal#validate-that-the-private-link-connection-works)
to ensure that the Key Vault domain name resolves to the Private Endpoint IP
address you've configured.

```shell-session
$ nslookup <keyvault-name>.vault.azure.net

Non-authoritative answer:
Name:
Address:  10.0.2.5 (private IP address)
Aliases:  <keyvault-name>.vault.azure.net
          <keyvault-name>.privatelink.vaultcore.azure.net
```

The secrets engine doesn't require special configuration to communicate with a
Key Vault instance over an Azure Private Endpoint. For example, the given [KMS
configuration](/vault/docs/secrets/key-management/azurekeyvault#configuration)
will result in the secrets engine resolving a Key Vault domain name of
`keyvault-name.vault.azure.net` to the Private Endpoint IP address. Note that
it's possible to change the Key Vault DNS suffix using the
[environment](/vault/api-docs/secret/key-management/azurekeyvault#environment)
configuration parameter or `AZURE_ENVIRONMENT` environment variable.


## Terraform example 

If you are familiar with [Terraform](/terraform/), you can use it to deploy the
necessary Azure infrastructure.

```hcl
provider "azuread" {
  version = "=0.11.0"
}

provider "azurerm" {
  features {
    key_vault {
      purge_soft_delete_on_destroy = true
    }
  }
}

resource "random_id" "app_rg_name" {
  byte_length = 3
}

resource "random_id" "keyvault_name" {
  byte_length = 3
}

data "azurerm_client_config" "current" {}

resource "azuread_application" "key_vault_app" {
  name                       = "app-${random_id.app_rg_name.hex}"
  homepage                   = "http://homepage${random_id.app_rg_name.b64_url}"
  identifier_uris            = ["http://uri${random_id.app_rg_name.b64_url}"]
  reply_urls                 = ["http://replyur${random_id.app_rg_name.b64_url}"]
  available_to_other_tenants = false
  oauth2_allow_implicit_flow = true
}

resource "azuread_service_principal" "key_vault_sp" {
  application_id               = azuread_application.key_vault_app.application_id
  app_role_assignment_required = false
}

resource "random_password" "password" {
  length           = 24
  special          = true
  override_special = "%@"
}

resource "azuread_service_principal_password" "key_vault_sp_pwd" {
  service_principal_id = azuread_service_principal.key_vault_sp.id
  value                = random_password.password.result
  end_date             = "2099-01-01T01:02:03Z"
}

resource "azurerm_resource_group" "key_vault_rg" {
  name     = "learn-rg-${random_id.app_rg_name.hex}"
  location = "West US"
}

resource "azurerm_key_vault" "key_vault_kv" {
  name                = "learn-keyvault-${random_id.keyvault_name.hex}"
  location            = azurerm_resource_group.key_vault_rg.location
  resource_group_name = azurerm_resource_group.key_vault_rg.name
  sku_name            = "premium"
  soft_delete_enabled = true
  tenant_id           = data.azurerm_client_config.current.tenant_id

  access_policy {
    tenant_id = data.azurerm_client_config.current.tenant_id
    object_id = data.azurerm_client_config.current.object_id
    key_permissions = [
      "backup",
      "create",
      "decrypt",
      "delete",
      "encrypt",
      "get",
      "import",
      "list",
      "purge",
      "recover",
      "restore",
      "sign",
      "unwrapKey",
      "update",
      "verify",
      "wrapKey"
    ]
  }

  access_policy {
    tenant_id = data.azurerm_client_config.current.tenant_id
    object_id = azuread_service_principal.key_vault_sp.object_id
    key_permissions = [
      "create",
      "delete",
      "get",
      "import",
      "update"
    ]
  }
}

output "key_vault_1_name" {
  value = azurerm_key_vault.key_vault_kv.name
}

output "tenant_id" {
  value = data.azurerm_client_config.current.tenant_id
}

output "client_id" {
  value = azuread_application.key_vault_app.application_id
}

output "client_secret" {
  value = azuread_service_principal_password.key_vault_sp_pwd.value
}
```
